#ifndef RTPPARSE_RTP_PACKET_H
#define RTPPARSE_RTP_PACKET_H

#include <cstdint>
#include <cstddef>
#include <arpa/inet.h>

// 零拷贝优化
// FEC

namespace Rtp {

    class RtpPacket {
    public:
        struct Header {
			//MS_LITTLE_ENDIAN
			uint8_t csrcCount : 4; //4bits CSRC计数，指示CSRC标识符的数量
			uint8_t extension : 1; //1bit 扩展标志，指示RTP包是否有扩展头
			uint8_t padding : 1;  //1bit 填充标志，指示RTP包是否有填充字节
			uint8_t version : 2; //2bits 版本号，RTP版本号为2 
			uint8_t payloadType : 7;  // 7bits 有效载荷类型，指示RTP包的有效载荷类型
			uint8_t marker : 1;  // 1bit 标记位，通常用于指示重要的事件或帧

            uint16_t sequenceNumber; // 16bits 序列号，RTP包的序列号，用于检测丢包和排序
			uint32_t timestamp; // 32bits 时间戳，RTP包的时间戳，用于同步和时序控制
			uint32_t ssrc;     // 32bits 同步源标识符（SSRC），唯一标识RTP流的源
        };

    private:
		/* Struct for RTP header extension. */
		struct HeaderExtension {
			uint16_t id;
			uint16_t length; // Size of value in multiples of 4 bytes.
			uint8_t value[1];
		};

	private:
		/* Struct for One-Byte extension. */
		struct OneByteExtension {
			//MS_LITTLE_ENDIAN
			uint8_t len : 4;
			uint8_t id : 4;
			uint8_t value[1];
		};
	private:
		/* Struct for Two-Bytes extension. */
		struct TwoBytesExtension {
			uint8_t id;
			uint8_t len;
			uint8_t value[1];
		};

	public:
		/* Struct for replacing and setting header extensions. */
		struct GenericExtension
		{
			GenericExtension(uint8_t id, uint8_t len, uint8_t* value) : id(id), len(len), value(value){};

			uint8_t id;
			uint8_t len;
			uint8_t* value;
		};
    public:
        static const size_t HeaderSize{ 12 };
        static bool IsRtp(const uint8_t* data, size_t len) {
			// NOTE: RtcpPacket::IsRtcp() must always be called before this method.
			auto* header = const_cast<Header*>(reinterpret_cast<const Header*>(data));

			// clang-format off
			return (
				(len >= HeaderSize) &&
				// DOC: https://tools.ietf.org/html/draft-ietf-avtcore-rfc5764-mux-fixes
				(data[0] > 127 && data[0] < 192) &&
				// RTP Version must be 2.
				(header->version == 2)
			);
			// clang-format on
		}

		static RtpPacket* Parse(const uint8_t* data, size_t len);
        RtpPacket(Header *header, 
			HeaderExtension *headerExtension, 
			const uint8_t *payload, 
			size_t payloadLength, 
			uint8_t payloadPadding, 
			size_t size);

        
        // Add methods to handle RTP packet data, parsing, etc.
        // For example, methods to set/get RTP header fields, payload, etc.
	public:
		const uint8_t* GetData() const {
			return reinterpret_cast<const uint8_t*>(this->header);
		}

		size_t GetSize() const {
			return this->size;
		}

		uint8_t GetPayloadType() const {
			return this->header->payloadType;
		}

		size_t GetPayloadLength() const
		{
			return this->payloadLength;
		}

		bool HasMarker() const {
			return this->header->marker;
		}

		uint16_t GetSequenceNumber() const {
			return uint16_t { ntohs(this->header->sequenceNumber) };
		}

		uint32_t GetTimestamp() const {
			return uint32_t { ntohl(this->header->timestamp) };
		}

		uint32_t GetSsrc() const {
			return uint32_t { ntohl(this->header->ssrc) };
		}

		bool HasOneByteExtensions() const {
			//当 RTP 头部扩展字段的前 2 字节等于 0xBEDE 时，表示后续扩展使用单字节格式
			return GetHeaderExtensionId() == 0xBEDE;   // 在RFC 5285 0xBEDE是单字节扩展的魔数标识符(Magic Number)
		}

		uint16_t GetHeaderExtensionId() const {
			if (!this->headerExtension) {
				return 0u;
			}

			return uint16_t { ntohs(this->headerExtension->id) };
		}

		bool IsKeyFrame() const {

			// payload type (PT) 字段本身不能直接标识关键帧，但是可以间接来判断，具体实现取决于编码方式
			// 通过 PT 值知道是 H.264/VP8/H.265，从而选择对应的解析方式
			// 在mediasoup中是有实现的
			return false;
		}

		void SetMidExtensionId(uint8_t id) {
			this->midExtensionId = id;
		}

		void SetRidExtensionId(uint8_t id) {
			this->ridExtensionId = id;
		}

		void SetRepairedRidExtensionId(uint8_t id) {
			this->rridExtensionId = id;
		}

		void SetAbsSendTimeExtensionId(uint8_t id) {
			this->absSendTimeExtensionId = id;
		}

		void SetTransportWideCc01ExtensionId(uint8_t id) {
			this->transportWideCc01ExtensionId = id;
		}
		
    private:
       Header *header { nullptr };
	   /** CSRC 可选字段 用于标识那些对RTP负载中的媒体内容有贡献的源(SSRC), 
		* 这些源不是同步源(SSRC)但它们的媒体数据被混合到了同一个RTP流中。
		* 例如，在一个音频会议中，多个说话者的音频被混合成一个RTP流，
		* 那么每个说话者的SSRC就会被列在CSRC列表中
		*/
	   uint8_t *csrcList { nullptr };
	   HeaderExtension *headerExtension { nullptr };
	   uint8_t *payload { nullptr };
	   size_t payloadLength { 0u };
	   uint8_t payloadPadding { 0u };
	   size_t size { 0u }; // Total size of the RTP packet including header, CS

	   uint8_t midExtensionId { 0u };
	   uint8_t ridExtensionId { 0u };
	   uint8_t rridExtensionId { 0u };
	   uint8_t absSendTimeExtensionId { 0u };
	   uint8_t transportWideCc01ExtensionId { 0u };
    };
}

#endif